package com.atguigu.security.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.reactive.PathRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.UserDetailsRepositoryReactiveAuthenticationManager;
import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.server.SecurityWebFilterChain;

/**
 * @author Jungle
 * @create 2024-01-17 21:54
 */
@EnableReactiveMethodSecurity
@Configuration
public class AppSecurityConfiguration {
    @Autowired
    private ReactiveUserDetailsService reactiveUserDetailsService;

    @Bean
    SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
        // 1、定义哪些请求需要认证，哪些不需要
        http.authorizeExchange(authorize -> {
            // 2、允许所有人都访问静态资源
            authorize.matchers(PathRequest.toStaticResources().atCommonLocations()).permitAll();
            // 3、剩下的所有请求都需要（登录）
            authorize.anyExchange().authenticated();

        });
        // 2、开启默认的表单登录
        http.formLogin(formLoginSpec -> {
        // 如果想用自己的登录页面
        //     formLoginSpec.loginPage("/haha");
        });

        // 3、安全控制
        http.csrf(ServerHttpSecurity.CsrfSpec::disable);


        // 4、配置 认证规则  如何去数据库中查询到用户 SpringSecurity 底层使用 ReactiveAuthenticationManager 去查询用户信息
        // ReactiveAuthenticationManager 有一个实现是
            // UserDetailsRepositoryReactiveAuthenticationManager ：用户信息去数据库汇总查
        // UDRespAM 需要 ReactiveUserDetailsService
        // 我们只需要自己写一个 ReactiveUserDetailsService:响应式的用户详情查询服务

        http.authenticationManager(new UserDetailsRepositoryReactiveAuthenticationManager(reactiveUserDetailsService));


        // http.oauth2Login()

        return http.build();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
        // return new BCryptPasswordEncoder();
    }
}
